home *** CD-ROM | disk | FTP | other *** search
Text File | 2000-03-26 | 14.4 KB | 465 lines | [TEXT/R*ch] |
- % Copyright (C) 1995, 2000 Aladdin Enterprises. All rights reserved.
- %
- % This file is part of Aladdin Ghostscript.
- %
- % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
- % or distributor accepts any responsibility for the consequences of using it,
- % or for whether it serves any particular purpose or works at all, unless he
- % or she says so in writing. Refer to the Aladdin Ghostscript Free Public
- % License (the "License") for full details.
- %
- % Every copy of Aladdin Ghostscript must include a copy of the License,
- % normally in a plain ASCII text file named PUBLIC. The License grants you
- % the right to copy, modify and redistribute Aladdin Ghostscript, but only
- % under certain conditions described in the License. Among other things, the
- % License requires that the copyright notice and this notice be preserved on
- % all copies.
-
- % $Id: gs_cidfn.ps,v 1.3 2000/03/10 04:53:25 lpd Exp $
- % ProcSet for implementing CIDFont and CIDMap resources.
- % When this is run, systemdict is still writable.
-
- % ---------------- Defining CIDFont resources ---------------- %
-
- % Define a CIDFont resource. This is the defineresource implementation for
- % the CIDFont resource category.
-
- /.cidfonttypes where { pop } { /.cidfonttypes 6 dict def } ifelse
- .cidfonttypes begin
-
- % The key in .cidfonttypes is the CIDFontType value;
- % the value is a procedure that takes a font name and the CIDFont dictionary
- % and replaces the latter with a real font.
-
- 0 { % CIDFontType 0 = FontType 9
- currentglobal 3 1 roll dup gcheck setglobal
- dup /FontType 9 put
- dup /FontMatrix known not {
- dup /FontMatrix [0.001 0 0 0.001 0 0] put
- dup /FDArray get {
- /FontMatrix get [1000 0 0 1000 0 0] 1 index concatmatrix pop
- } forall
- } if
- dup /FDArray get mark exch {
- % Add pro forma entries
- currentglobal exch dup gcheck setglobal
- dup /FontType 1 put
- dup /CharStrings mark /.notdef () .dicttomark put
- dup /Encoding [] put
- % Create a dummy Subrs array now, if there isn't one here
- % already (which can only happen if we're giving another
- % name to an existing font).
- dup /Private get dup /Subrs known not {
- dup /SubrCount .knownget {
- array 1 index /Subrs 3 -1 roll put
- } if readonly
- } if pop
- exch setglobal
- dup /FontName .knownget not { () } if exch .buildfont1 exch pop
- } forall ] 1 index /FDepVector 3 -1 roll put
- 3 -1 roll setglobal
- 1 index exch .buildfont9 exch pop
- } bind def
-
- 1 { % CIDFontType 1 = FontType 10
- dup /FontType 10 put
- 1 index exch .buildfont10 exch pop
- } bind def
-
- 2 { % CIDFontType 2 = FontType 11
- dup /FontType 11 put
- 1 index exch .buildfont11 exch pop
- } bind def
-
- end % .cidfonttypes
-
- % ---------------- Reading CIDFontType 0 files ---------------- %
-
- 30 dict begin
-
- % We add the following entries to the CIDFont dictionary, in addition to
- % the ones documented by Adobe:
- % ReadString - procedure for reading a string from the binary data
- % SubrCache - dictionary for caching Subr arrays
- % For CIDFonts where we read the data from disk incrementally:
- % DataOffset - starting position of data in file
- % (if data are in hex) OffsetMap - map from logical data positions to
- % physical positions in file
-
- /StartData % <(Binary)|(Hex)> <datalength> StartData -
- % (currentdict is CID font dict)
- { % If we're loading a resource file, we can just save a
- % pointer to the binary data and load it incrementally.
- % Check for this by opening the resource file,
- % positioning it to currentfile's position plus the
- % data length, and checking for %%EndData.
- mark
- { currentfile fileposition
- CIDFontName 100 string ResourceFileName (r) file
- mark
- { % Stack: (Binary)|(Hex) length -mark- pos resfile
- % -mark-
- 5 index (Hex) eq
- { 1 index 3 index setfileposition
- 1 index 5 index .skiphex
- %**************** SKIP > AND WHITESPACE SOMEHOW
- }
- { 1 index 3 index 6 index add setfileposition
- }
- ifelse
- 1 index 9 string readstring pop (%%EndData) ne { stop } if
- }
- .internalstopped { cleartomark closefile stop } if
- pop % pop the mark
- }
- .internalstopped
- { % File is not positionable, load the data now.
- cleartomark exch (Hex) eq
- { { currentfile exch readhexstring pop } }
- { { currentfile exch readstring pop } }
- ifelse /ReadString exch def
- dup 65535 le {
- % readstring with a 0-length string causes a rangecheck,
- % but a data length of 0 is allowed.
- string dup () ne { ReadString } if
- } {
- mark exch
- { dup 0 eq { pop exit } if
- dup 65535 min dup string ReadString
- 3 1 roll sub
- }
- loop ]
- } ifelse
- /GlyphData exch def
- % If we were reading hex data, skip past the >.
- /ReadString load 2 get { readhexstring } 0 get eq {
- currentfile 0 (>) /SubFileDecode filter dup flushfile closefile
- } if
- /.vmreadstring cvx
- }
- { % File is positionable, just save a pointer.
- % Stack: (Binary)|(Hex) length -mark- pos file
- 4 1 roll
- /DataOffset exch def
- pop /GlyphData exch def
- exch (Hex) eq
- { % Hex data, build the offset map.
- .buildoffsetmap
- /.hexreadstring
- }
- { % Binary data, just skip over it.
- currentfile DataOffset GlyphData add setfileposition
- /.binaryreadstring
- }
- ifelse cvx
- 2 packedarray cvx
- }
- ifelse /ReadString exch def
- /SubrCache 10 dict def
- CIDFontName currentdict /CIDFont defineresource pop
- end % CID font dict
- end % resource category dict
- } bind def
-
- % Skip a given distance in an ASCIIHex encoded file. We use this at
- % rendering time as well.
- /.skiphex % <file> <count> .skiphex -
- { exch /ASCIIHexDecode filter dup 3 -1 roll () /SubFileDecode filter
- dup flushfile closefile closefile
- } bind def
-
- % Build the map from logical offsets to physical offsets in ASCIIHex
- % encoded data.
- /.buildoffsetmap
- { /OffsetMap GlyphData 256 idiv 8000 min array def
- 2 dict begin
- /block GlyphData OffsetMap length idiv def
- 0 1 OffsetMap length 1 sub
- { OffsetMap exch currentfile fileposition put
- currentfile block .skiphex
- }
- for
- GlyphData block mod dup 0 eq
- { pop }
- { currentfile exch .skiphex }
- ifelse
- end % scratch dict
- } bind def
-
- % Some Adobe fonts include the line
- % /Setup /cid_Setup load def
- % This is apparently included only to prevent proper, conforming PostScript
- % interpreters (as opposed to ATM or a special Adobe font loader) from
- % loading the font, since Setup is not referenced anywhere else in the file.
- %/cid_Setup { } def
-
- currentdict end
-
- % ---------------- Rendering ---------------- %
-
- % ------ Generic ------ %
-
- % Read a string at a given offset in a "file" (binary file, ASCII hex file,
- % or GlyphData in RAM).
- /.binaryreadstring % <pos> <string> <file> .binaryreadstring <string>
- { dup 4 -1 roll DataOffset add setfileposition exch readstring pop
- } bind def
- /.hexreadstring % <pos> <string> <file> .hexreadstring <string>
- { % Use the OffsetMap to get to the block of hex data,
- % then skip to the correct position by reading.
- GlyphData OffsetMap length idiv
- % Stack: pos string file blocklen
- 3 index 1 index idiv OffsetMap exch get
- 2 index exch setfileposition
- % Skip the next (pos % blocklen) hex bytes.
- 4 -1 roll exch mod 1 index exch .skiphex
- % Stack: string file
- exch readhexstring pop
- } bind def
- /.vmreadstring % <pos> <string> .vmreadstring <vmstring>
- { GlyphData .stringsreadstring
- } bind def
- /.stringsreadstring % <pos> <string> <strings> .stringsreadstring
- % <vmstring>
- { dup type /stringtype eq
- { 3 1 roll length getinterval
- }
- { { % Stack: pos string glyphdata
- dup 0 get length dup 4 index gt { exit } if
- 4 -1 roll exch sub 3 1 roll
- dup length 1 sub 1 exch getinterval
- }
- loop
- % Stack: pos string glyphdata glyphdata[0]length
- % We know no request can span more than 2 strings.
- 3 index 3 index length add 1 index le
- { % Request fits in a single string: just return a substring.
- pop 0 get 3 1 roll length getinterval
- }
- { % Request spans 2 strings. Copy the first part.
- 1 index 0 get 4 index 3 -1 roll 1 index sub getinterval
- 2 index copy
- % Copy the second part.
- % Stack: pos str glyphdata str1
- length exch 1 get 0 3 index length
- 3 index sub getinterval 2 index 3 1 roll putinterval
- exch pop
- }
- ifelse
- }
- ifelse
- } bind def
-
- % Interpret a byte string as a (big-endian) integer.
- /.cvbsi % <bytes> .cvbsi <int>
- { 0 exch { exch 8 bitshift add } forall
- } bind def
-
- % Read an integer from binary data.
- /.readint % <pos> <nbytes> .readint <int>
- { string ReadString .cvbsi
- } bind def
-
- % Read the glyph data for a given CID. The CIDFont is currentdict.
- % Note that the data must be read into the same VM as the CharStrings
- % dictionary of the selected subfont.
- /.readglyphdata { % <cid> .readglyphdata <subfont> <string|null>
- currentdict /GlyphDirectory .knownget {
- dup type /arraytype eq {
- 1 index get
- } {
- 1 index .knownget not { null } if
- } ifelse
- % Stack: cid string|null
- dup null ne { exch pop .readgdirdata } { pop .readbytedata } ifelse
- } {
- % Stack: cid
- .readbytedata
- } ifelse
- } bind def
- /.readgdirdata { % <string|null> .readgdirdata <subfont> <string|null>
- dup null eq {
- FDepVector 0 get exch
- } {
- FDBytes 0 eq {
- FDepVector 0 get exch
- } {
- % Note: FDBytes > 1 is not supported.
- dup 0 get FDepVector exch get
- exch dup length 1 sub 1 exch getinterval
- } ifelse
- } ifelse
- } bind def
- /.readbytedata { % <cid> .readbytedata <subfont> <string|null>
- dup dup 0 ge exch CIDCount lt and {
- FDBytes GDBytes add mul CIDMapOffset add
- dup FDBytes .readint exch
- FDBytes add dup GDBytes .readint
- exch GDBytes add FDBytes add GDBytes .readint
- % Stack: fd pos nextpos
- 1 index sub dup 0 eq {
- pop pop pop FDepVector 0 get null
- } {
- % Stack: fd pos len
- FDepVector 4 -1 roll get
- dup /CharStrings get gcheck .currentglobal exch .setglobal
- % Stack: pos len subfont global
- 4 2 roll string ReadString exch .setglobal
- } ifelse
- } {
- pop FDepVector 0 get null
- } ifelse
- } bind def
-
- % ------ CIDFontType 0 ------ %
-
- % Read some Subrs for the current Type 1 subfont.
- % The subfont's Private dict is currentdict; the CIDFont itself is the
- % next dictionary on the stack.
- /.readsubrs { % <Subrs> <start> .readsubrs <Subrs>
- 1 SubrCount 1 sub {
- dup SDBytes mul SubrMapOffset add
- dup SDBytes .readint exch SDBytes add SDBytes .readint
- 1 index sub string ReadString 2 index 3 1 roll put
- } for
- } bind def
-
- % Ensure that all the Subrs for the current Type 1 subfont are loaded.
- % The subfont's Private dict is currentdict; the CIDFont itself is the
- % next dictionary on the stack.
- /.loadsubrs {
- currentdict /SubrMapOffset .knownget {
- Subrs length 0 eq { true } { Subrs 0 get null ne } ifelse {
- pop % We've already loaded the Subrs.
- } {
- currentglobal exch currentdict gcheck setglobal
- SubrCache 1 index .knownget {
- % We've already loaded some Subrs at this offset.
- % Make sure we've got as many as we need.
- dup length SubrCount lt {
- % We need to load more.
- SubrCount array exch 1 index copy length .readsubrs
- SubrCache 3 -1 roll 2 index put
- } if
- } {
- % We haven't loaded any Subrs at this offset yet.
- SubrCount array 0 .readsubrs
- SubrCache 3 -1 roll 2 index put
- } ifelse
- Subrs copy pop setglobal
- } ifelse
- } if
- } bind def
-
- % BuildGlyph procedure for CIDFontType 0.
- % ****** WHY NOT USE .type1execchar FOR THIS? ******
- % The name %Type9BuildGlyph is known to the interpreter.
- /.cid0buildstring 10 string def
- (%Type9BuildGlyph) cvn { % <cidfont> <cid> %Type9BuildGlyph -
- .currentglobal 3 1 roll 1 index gcheck .setglobal
- 1 index begin
- dup .readglyphdata dup null eq {
- % Substitute CID 0. **** WRONG ****
- pop pop 0 .readglyphdata
- } if
- % Stack: cidfont cid subfont charstring
- dup null eq { pop pop pop pop } { %**** WRONG ****
- 4 -1 roll pop
- exch dup /Private get begin .loadsubrs end
- 3 -1 roll //.cid0buildstring cvs cvn 3 1 roll
- dup /CharStrings get 3 index 4 -1 roll put
- setfont
- dup .glyphwidth setcharwidth
- 0 0 moveto glyphshow
- } ifelse %**** WRONG ****
- end
- .setglobal
- } bind def
-
- % ------ CIDFontType 2 ------ %
-
- % BuildGlyph procedure for CIDFontType 2.
- % ****** ADD THE OUTLINE STRING AS AN ARGUMENT TO .type42execchar. ******
- % The name %Type11BuildGlyph is known to the interpreter.
- (%Type11BuildGlyph) cvn { % <cidfont> <cid> %Type11BuildGlyph -
- .currentglobal 3 1 roll 1 index gcheck .setglobal
- 1 index begin
- % We must be prepared for out-of-range CIDs.
- dup GDBytes mul GDBytes string CIDMap
- mark 4 1 roll { .stringsreadstring } .internalstopped {
- %**** 0 IS WRONG
- cleartomark 0 GDBytes string CIDMap .stringsreadstring
- } {
- exch pop
- } ifelse .cvbsi
- % Stack: cidfont cid glyphindex
- 1 index exch .type42execchar
- end
- .setglobal
- } bind def
-
- % ---------------- Define resources ---------------- %
-
- languagelevel exch 2 .setlanguagelevel
-
- % Define the CIDInit ProcSet resource.
- % The ProcSet dictionary is still on the stack.
-
- /CMap /Generic /Category findresource dup length dict .copydict
- /Category defineresource pop
- % We might have loaded CMap support already.
- /CIDInit /ProcSet 2 copy resourcestatus {
- pop pop findresource dup length 4 index length add dict .copydict
- 4 -1 roll exch .copydict
- } {
- 3 -1 roll
- } ifelse exch defineresource pop
-
- % Define the CIDFont resource category.
- % We break out .buildcidfont because it appears that at least for
- % Type 32 (CIDFontType 4) fonts, the font can be registered in the Font
- % category with only a CIDFontType and no FontType.
- /.buildcidfont { % <name> <fontdict> .buildcidfont
- % <name> <cidfont>
- dup /CIDFontType get //.cidfonttypes exch get exec
- } odef
-
- /CIDFont /Generic /Category findresource dup length dict .copydict
- dup /InstanceType /dicttype put
- dup /DefineResource {
- .buildcidfont
- /Generic /Category findresource /DefineResource get exec
- } put
- /Category defineresource pop
-
- % Add the new FontType resources.
-
- 9 1 11 { dup /FontType defineresource pop } for
-
- % Add the new FMapType resource.
-
- 9 dup /FMapType defineresource pop
-
- % Define the CIDMap resource category.
- % These aren't documented, but it's clear what they are for:
- % to give names to CIDMaps for CIDFontType 2 fonts.
-
- /CIDMap /Generic /Category findresource dup length dict .copydict
- dup /.CheckResource {
- % Allow either a string or an array of strings.
- dup type dup /stringtype eq
- { pop true
- }
- { dup /arraytype eq exch /packedarraytype eq or
- { true exch { type /stringtype ne { pop false exit } if } forall
- }
- { false
- }
- ifelse
- }
- ifelse
- } bind put
- /Category defineresource pop
-
- .setlanguagelevel
-